<template>
  <div class="heatwave-container">
<!--    <h2>海洋热浪事件可视化</h2>-->
<!--    <div class="unit-desc">-->
<!--      <p>本页面展示了海洋热浪事件的多维特征，包括纬度、经度、持续时间、最大SST异常、累积SST异常等。</p>-->
<!--      <p>数据来源：<a href="https://www.ncei.noaa.gov/access/metadata/landing-page/bin/iso?id=gov.noaa.nodc:0166882" target="_blank">NOAA NCEI</a></p>-->
<!--      <p>单位说明：<br>-->
<!--        纬度：°N<br>-->
<!--        经度：°E<br>-->
<!--        持续时间：天<br>-->
<!--        最大SST异常：°C<br>-->
<!--        累积SST异常：°C·d<br>-->
<!--        最大基线调整异常：°C<br>-->
<!--        DHW峰值：°C·week-->
<!--      </p>-->
<!--    </div>-->
    <div v-loading="loading" class="chart-grid">
      <div id="parallelChart" ref="parallelRef" class="chart-container"></div>
<!--      <div id="sankeyChart" ref="sankeyRef" class="chart-container"></div>-->
<!--      <div id="parallelSankeyChart" ref="parallelSankeyRef" class="chart-container"></div>-->
<!--      <div id="sunburstChart" ref="sunburstRef" class="chart-container"></div>-->
<!--      <div id="lineChart" ref="lineRef" class="chart-container"></div>-->

<!--      <div id="scatter3d" ref="scatter3dRef" class="chart-container chart-container-3d"></div>-->
<!--      <button @click="toggle3DScatterView" class="chart-action-button">-->
<!--        {{ get3DViewButtonText() }}-->
<!--      </button>-->

<!--      <div id="timeSeries" ref="timeSeriesRef" class="chart-container"></div>-->
<!--      <div id="scatterMatrix" ref="scatterMatrixRef" class="chart-container matrix-container"></div>-->
      <div id="transitionChart" ref="transitionRef" class="chart-container transition-clickable">
        <div class="click-prompt">点击切换图表形式</div>
      </div>
<!--      <div id="treemapSunburstChart" ref="treemapSunburstRef" class="chart-container transition-clickable">-->
<!--        <div class="click-prompt">点击切换图表形式</div>-->
<!--      </div>-->
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as Papa from 'papaparse'; // CSV 解析库
import Plotly from 'plotly.js-dist'; // Plotly 图表库
import * as echarts from 'echarts'; // ECharts 图表库

// 定义数据接口，确保类型安全
interface HeatwaveData {
  event_id: string;
  lat: number | string;
  lon: number | string;
  start_date: string;
  duration: number | string;
  max_anomaly: number | string;
  cumulative_anomaly: number | string;
  baa_max: number | string;
  DHW_peak: number | string;
  [key: string]: any; // 允许其他未知属性
}

// 定义 3D/2D 视图状态的联合类型
type ThreeDViewState = '3D' | '2D_XZ' | '2D_YZ';

export default defineComponent({
  name: 'Heatwave',
  setup() {
    // 加载状态
    const loading = ref(true);

    // DOM 引用，用于挂载图表
    const parallelRef = ref<HTMLElement | null>(null);
    const sankeyRef = ref<HTMLElement | null>(null);
    const parallelSankeyRef = ref<HTMLElement | null>(null);
    const sunburstRef = ref<HTMLElement | null>(null);
    const lineRef = ref<HTMLElement | null>(null);
    const scatter3dRef = ref<HTMLElement | null>(null); // 这个 div 将用于渲染 3D 或 2D 散点图
    const timeSeriesRef = ref<HTMLElement | null>(null);
    const scatterMatrixRef = ref<HTMLElement | null>(null);
    const transitionRef = ref<HTMLElement | null>(null);
    const treemapSunburstRef = ref<HTMLElement | null>(null);

    // ECharts 实例，用于处理切换逻辑
    let transitionChart: echarts.ECharts | null = null;
    let treemapSunburstChart: echarts.ECharts | null = null;

    // ECharts 切换状态
    let currentTransitionOption: 'scatter' | 'bar' = 'scatter';
    let currentTreemapSunburstOption: 'treemap' | 'sunburst' = 'treemap';

    // 3D/2D 散点图的当前视图状态，默认为 3D
    const current3DView = ref<ThreeDViewState>('3D');
    // 存储从 CSV 加载的原始数据
    let heatwaveRawData: HeatwaveData[] = [];

    // --- 数据分类与处理函数 ---
    const categorize = {
      getYear: (d: string) => d ? String(d).slice(0, 4) : '未知',
      latBand: (lat: number) => {
        if (lat >= 45) return '高纬（≥45°N）';
        if (lat >= 40) return '中纬（40-45°N）';
        return '低纬（<40°N）';
      },
      durationLevel: (d: number) => {
        if (d >= 25) return '长期（≥25天）';
        if (d >= 15) return '中期（15-24天）';
        if (d >= 10) return '短期（10-14天）';
        return '极短（<10天）';
      },
      anomalyLevel: (a: number) => {
        if (a > 7) return '极强（>7°C）';
        if (a > 5) return '强（5-7°C）';
        if (a > 3) return '中（3-5°C）';
        return '弱（≤3°C）';
      }
    };

    const calculateAverage = (data: number[]): number => {
      if (data.length === 0) return 0;
      const total = data.reduce((sum, val) => sum + val, 0);
      return Number((total / data.length).toFixed(2));
    };

    // --- Plotly 图表绘制函数 ---

    /**
     * 绘制三维散点图
     * @param data 热浪事件数据
     */
    const draw3DScatterPlot = (data: HeatwaveData[]) => {
      if (!scatter3dRef.value) return;

      const traces = [{
        type: 'scatter3d',
        mode: 'markers',
        x: data.map(d => Number(d.lat)),
        y: data.map(d => Number(d.lon)),
        z: data.map(d => Number(d.max_anomaly)),
        marker: {
          size: data.map(d => Number(d.duration) / 2),
          color: data.map(d => Number(d.cumulative_anomaly)),
          colorscale: 'Viridis',
          colorbar: {
            title: { text: '累积SST异常 (°C·d)', font: { color: '#fff' } },
            tickfont: { color: '#fff' }
          },
          opacity: 0.8
        },
        text: data.map(d =>
          `事件ID: ${d.event_id}<br>` +
          `开始日期: ${d.start_date}<br>` +
          `持续时间: ${d.duration}天`
        ),
        hovertemplate:
          '<b>纬度</b>: %{x}°N<br>' +
          '<b>经度</b>: %{y}°E<br>' +
          '<b>最大SST异常</b>: %{z}°C<br>' +
          '%{text}<br>' +
          '<extra></extra>'
      }];

      const layout: Partial<Plotly.Layout> = {
        title: { text: '海洋热浪事件三维分布图', font: { size: 16, color: '#fff' } },
        scene: {
          xaxis: { title: { text: '纬度 (°N)', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444' },
          yaxis: { title: { text: '经度 (°E)', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444' },
          zaxis: { title: { text: '最大SST异常 (°C)', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444' },
          bgcolor: '#222',
          camera: {
            eye: { x: 1.5, y: 1.5, z: 1.5 }, // 默认 3D 视角
            center: { x: 0, y: 0, z: 0 },
            up: { x: 0, y: 0, z: 1 }
          }
        },
        paper_bgcolor: '#222',
        plot_bgcolor: '#222',
        showlegend: false,
        margin: { l: 0, r: 0, t: 30, b: 0 },
        height: 600 // 明确设置 3D 图表高度
      };

      const config = {
        displayModeBar: true,
        displaylogo: false,
        modeBarButtonsToAdd: [{
          name: '重置视图',
          icon: Plotly.Icons.home,
          click: function(gd: any) {
            Plotly.relayout(gd, {
              'scene.camera': {
                eye: {x: 1.5, y: 1.5, z: 1.5},
                center: {x: 0, y: 0, z: 0}
              }
            });
          }
        }]
      };
      Plotly.newPlot(scatter3dRef.value, traces, layout, config);
    };

    /**
     * 绘制二维 X-Z 散点图 (纬度 vs. 最大SST异常)
     * @param data 热浪事件数据
     */
    const draw2D_XZ_Plot = (data: HeatwaveData[]) => {
      if (!scatter3dRef.value) return;

      const traces = [{
        type: 'scatter', // 明确指定为 2D 散点图
        mode: 'markers',
        x: data.map(d => Number(d.lat)), // X 轴：纬度
        y: data.map(d => Number(d.max_anomaly)), // Y 轴：最大SST异常
        marker: {
          size: data.map(d => Number(d.duration) / 2),
          color: data.map(d => Number(d.cumulative_anomaly)),
          colorscale: 'Viridis',
          colorbar: {
            title: { text: '累积SST异常 (°C·d)', font: { color: '#fff' } },
            tickfont: { color: '#fff' }
          },
          opacity: 0.8
        },
        text: data.map(d =>
          `事件ID: ${d.event_id}<br>` +
          `纬度: ${d.lat}°N<br>` +
          `最大SST异常: ${d.max_anomaly}°C<br>` +
          `持续时间: ${d.duration}天`
        ),
        hovertemplate: '%{text}<extra></extra>'
      }];

      const layout: Partial<Plotly.Layout> = {
        title: { text: '纬度 vs. 最大SST异常 (2D 降维)', font: { size: 16, color: '#fff' } },
        xaxis: { title: { text: '纬度 (°N)', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444' },
        yaxis: { title: { text: '最大SST异常 (°C)', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444' },
        paper_bgcolor: '#222',
        plot_bgcolor: '#222',
        showlegend: false,
        margin: { l: 40, r: 20, t: 30, b: 40 },
        hovermode: 'closest',
        height: 600 // 匹配 3D 图表高度
      };

      const config = {
        displayModeBar: true,
        displaylogo: false
      };

      Plotly.newPlot(scatter3dRef.value, traces, layout, config);
    };

    /**
     * 绘制二维 Y-Z 散点图 (经度 vs. 最大SST异常)
     * @param data 热浪事件数据
     */
    const draw2D_YZ_Plot = (data: HeatwaveData[]) => {
      if (!scatter3dRef.value) return;

      const traces = [{
        type: 'scatter', // 明确指定为 2D 散点图
        mode: 'markers',
        x: data.map(d => Number(d.lon)), // X 轴：经度
        y: data.map(d => Number(d.max_anomaly)), // Y 轴：最大SST异常
        marker: {
          size: data.map(d => Number(d.duration) / 2),
          color: data.map(d => Number(d.cumulative_anomaly)),
          colorscale: 'Viridis',
          colorbar: {
            title: { text: '累积SST异常 (°C·d)', font: { color: '#fff' } },
            tickfont: { color: '#fff' }
          },
          opacity: 0.8
        },
        text: data.map(d =>
          `事件ID: ${d.event_id}<br>` +
          `经度: ${d.lon}°E<br>` +
          `最大SST异常: ${d.max_anomaly}°C<br>` +
          `持续时间: ${d.duration}天`
        ),
        hovertemplate: '%{text}<extra></extra>'
      }];

      const layout: Partial<Plotly.Layout> = {
        title: { text: '经度 vs. 最大SST异常 (2D 降维)', font: { size: 16, color: '#fff' } },
        xaxis: { title: { text: '经度 (°E)', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444' },
        yaxis: { title: { text: '最大SST异常 (°C)', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444' },
        paper_bgcolor: '#222',
        plot_bgcolor: '#222',
        showlegend: false,
        margin: { l: 40, r: 20, t: 30, b: 40 },
        hovermode: 'closest',
        height: 600 // 匹配 3D 图表高度
      };

      const config = {
        displayModeBar: true,
        displaylogo: false
      };

      Plotly.newPlot(scatter3dRef.value, traces, layout, config);
    };

    // --- 3D/2D 散点图切换逻辑 ---

    /**
     * 根据当前视图状态获取按钮文本
     */
    const get3DViewButtonText = () => {
      switch (current3DView.value) {
        case '3D':
          return '降维：纬度 vs. SST异常 (X-Z)';
        case '2D_XZ':
          return '降维：经度 vs. SST异常 (Y-Z)';
        case '2D_YZ':
          return '回到 3D 散点图';
        default:
          return '切换视角';
      }
    };

    /**
     * 切换 3D/2D 散点图视图
     */
    const toggle3DScatterView = () => {
      // 1. 清除当前 scatter3dRef 上的 Plotly 实例，为新图表腾出空间
      if (scatter3dRef.value && Plotly.d3.select(scatter3dRef.value).data().length > 0) {
          Plotly.purge(scatter3dRef.value);
      }

      // 2. 确定下一个视图状态
      const views: ThreeDViewState[] = ['3D', '2D_XZ', '2D_YZ'];
      const currentIndex = views.indexOf(current3DView.value);
      const nextIndex = (currentIndex + 1) % views.length;
      current3DView.value = views[nextIndex]; // 更新状态

      // 3. 根据新的视图状态绘制相应的图表
      if (heatwaveRawData.length > 0) {
        switch (current3DView.value) {
          case '3D':
            draw3DScatterPlot(heatwaveRawData);
            break;
          case '2D_XZ':
            draw2D_XZ_Plot(heatwaveRawData);
            break;
          case '2D_YZ':
            draw2D_YZ_Plot(heatwaveRawData);
            break;
        }
      }
    };

    // --- 其他图表绘制函数（与之前版本相同，未修改）---

    // ECharts Treemap/Sunburst
    const processForTreemapSunburst = (data: HeatwaveData[]) => {
      const hierarchy: { [year: string]: { [latBand: string]: { [durationLevel: string]: number } } } = {};
      data.forEach(row => {
        const year = categorize.getYear(row.start_date);
        const lat = Number(row.lat);
        const duration = Number(row.duration);
        if (isNaN(lat) || isNaN(duration)) return;
        const latBand = categorize.latBand(lat);
        const durationLevel = categorize.durationLevel(duration);
        if (!hierarchy[year]) hierarchy[year] = {};
        if (!hierarchy[year][latBand]) hierarchy[year][latBand] = {};
        if (!hierarchy[year][latBand][durationLevel]) hierarchy[year][latBand][durationLevel] = 0;
        hierarchy[year][latBand][durationLevel]++;
      });
      const rootChildren: any[] = [];
      for (const year in hierarchy) {
        const yearNode: any = { name: `${year}年`, children: [] };
        for (const latBand in hierarchy[year]) {
          const latBandNode: any = { name: latBand, children: [] };
          for (const durationLevel in hierarchy[year][latBand]) {
            latBandNode.children.push({
              name: durationLevel,
              value: hierarchy[year][latBand][durationLevel]
            });
          }
          yearNode.children.push(latBandNode);
        }
        rootChildren.push(yearNode);
      }
      return { name: '热浪事件', children: rootChildren };
    };

    const drawTreemapSunburstChart = (data: HeatwaveData[]) => {
      if (!treemapSunburstRef.value) {
        console.error("treemapSunburstRef.value is null or undefined. Cannot initialize ECharts Treemap/Sunburst.");
        return;
      }
      const processedData = processForTreemapSunburst(data);
      if (!processedData.children || processedData.children.length === 0) {
        console.warn("No valid data to render Treemap/Sunburst chart.");
        return;
      }
      const treemapOption = {
        title: { text: '热浪事件层级分布 (树图)', textStyle: { color: '#fff' } },
        tooltip: {
          formatter: function (info: any) {
            var value = info.value;
            var treePathInfo = info.treePathInfo;
            var treePath = [];
            for (var i = 1; i < treePathInfo.length; i++) {
              treePath.push(treePathInfo[i].name);
            }
            return [
              '<div class="tooltip-title">' + treePath.join(' / ') + '</div>',
              '数量: ' + value + '个事件'
            ].join('');
          }
        },
        series: [{
            type: 'treemap', id: 'heatwave-hierarchy', animationDurationUpdate: 1000, roam: false, nodeClick: false,
            data: processedData.children, universalTransition: true,
            label: { show: true, formatter: '{b}', color: '#eee', fontSize: 12 },
            breadcrumb: { show: false }, itemStyle: { borderColor: '#232323' }
          }
        ],
        backgroundColor: '#232323',
      };
      const sunburstOption = {
        title: { text: '热浪事件层级分布 (旭日图)', textStyle: { color: '#fff' } },
        tooltip: {
          formatter: function (info: any) {
            var value = info.value;
            var treePathInfo = info.treePathInfo;
            var treePath = [];
            for (var i = 1; i < treePathInfo.length; i++) {
              treePath.push(treePathInfo[i].name);
            }
            return [
              '<div class="tooltip-title">' + treePath.join(' / ') + '</div>',
              '数量: ' + value + '个事件'
            ].join('');
          }
        },
        series: [{
            type: 'sunburst', id: 'heatwave-hierarchy', radius: ['20%', '90%'], animationDurationUpdate: 1000,
            nodeClick: false, data: processedData.children, universalTransition: true,
            itemStyle: { borderWidth: 1, borderColor: 'rgba(255,255,255,.5)' },
            label: { show: true, formatter: '{b}', color: '#eee', fontSize: 10 },
            levels: [ {}, { r0: '20%', r: '40%', label: { rotate: 'radial' } }, { r0: '40%', r: '60%', label: { rotate: 'radial' } }, { r0: '60%', r: '90%', label: { rotate: 'radial' } } ]
          }
        ],
        backgroundColor: '#232323',
      };

      if (treemapSunburstChart) { treemapSunburstChart.dispose(); }
      treemapSunburstChart = echarts.init(treemapSunburstRef.value, null, { renderer: 'canvas', });
      treemapSunburstChart.setOption(treemapOption);
      currentTreemapSunburstOption = 'treemap';

      treemapSunburstRef.value.onclick = () => {
        if (currentTreemapSunburstOption === 'treemap') {
          treemapSunburstChart?.setOption(sunburstOption, true);
          currentTreemapSunburstOption = 'sunburst';
        } else {
          treemapSunburstChart?.setOption(treemapOption, true);
          currentTreemapSunburstOption = 'treemap';
        }
      };
    };

    // ECharts Transition Chart (Scatter to Bar)
    const drawTransitionChart = (data: HeatwaveData[]) => {
      if (!transitionRef.value) {
        console.error("transitionRef.value is null or undefined. Cannot initialize ECharts.");
        return;
      }
      const validData = data.filter(
        (row) => row.lat !== undefined && row.max_anomaly !== undefined && !isNaN(Number(row.lat)) && !isNaN(Number(row.max_anomaly)),
      );
      const latBands = ['低纬（<40°N）', '中纬（40-45°N）', '高纬（≥45°N）'];
      const groupedData: Record<string, { lat: number; anomaly: number }[]> = {
        '低纬（<40°N）': [], '中纬（40-45°N）': [], '高纬（≥45°N）': [],
      };
      validData.forEach((row) => {
        const lat = Number(row.lat);
        const anomaly = Number(row.max_anomaly);
        const band = categorize.latBand(lat);
        groupedData[band]?.push({ lat, anomaly });
      });

      const scatterOption = {
        title: { text: '纬度与最大SST异常分布', textStyle: { color: '#fff' } },
        xAxis: {
          type: 'value', name: '纬度 (°N)', nameTextStyle: { color: '#fff' }, axisLabel: { color: '#fff' },
          splitLine: { lineStyle: { color: '#444' } }, scale: true,
        },
        yAxis: {
          type: 'value', name: '最大SST异常 (°C)', nameTextStyle: { color: '#fff' }, axisLabel: { color: '#fff' },
          splitLine: { lineStyle: { color: '#444' } }, scale: true,
        },
        backgroundColor: '#232323',
        series: latBands.map((band, index) => ({
          type: 'scatter', id: band, dataGroupId: band,
          data: groupedData[band]?.map((d) => [d.lat, d.anomaly]) || [],
          universalTransition: { enabled: true, delay: (idx: number, count: number) => Math.random() * 400 },
          itemStyle: { color: ['#ff7f0e', '#2ca02c', '#1f77b4'][index] },
        })),
        tooltip: { trigger: 'item', formatter: (params: any) => `纬度: ${params.value[0]}°N<br>最大SST异常: ${params.value[1]}°C` },
      };

      const barOption = {
        title: { text: '各纬度带平均最大SST异常', textStyle: { color: '#fff' } },
        xAxis: {
          type: 'category', data: latBands, name: '纬度带', nameTextStyle: { color: '#fff' },
          axisLabel: { color: '#fff' },
        },
        yAxis: {
          type: 'value', name: '平均最大SST异常 (°C)', nameTextStyle: { color: '#fff' },
          axisLabel: { color: '#fff' }, splitLine: { lineStyle: { color: '#444' } },
        },
        backgroundColor: '#232323',
        series: [{
            type: 'bar', id: 'average',
            data: latBands.map((band, index) => ({
              value: calculateAverage(groupedData[band]?.map((d) => d.anomaly) || []),
              groupId: band, itemStyle: { color: ['#ff7f0e', '#2ca02c', '#1f77b4'][index] },
            })),
            universalTransition: { enabled: true, seriesKey: latBands, delay: (idx: number, count: number) => Math.random() * 400, },
          },
        ],
        tooltip: { trigger: 'item', formatter: (params: any) => `${params.name}<br>平均最大SST异常: ${params.value}°C`, },
      };

      if (transitionChart) { transitionChart.dispose(); }
      transitionChart = echarts.init(transitionRef.value, null, { renderer: 'canvas', });
      transitionChart.setOption(scatterOption);
      currentTransitionOption = 'scatter';

      transitionRef.value.onclick = () => {
        if (currentTransitionOption === 'scatter') {
          transitionChart?.setOption(barOption, true);
          currentTransitionOption = 'bar';
        } else {
          transitionChart?.setOption(scatterOption, true);
          currentTransitionOption = 'scatter';
        }
      };
    };

    // Plotly Parallel Coordinates Chart
    const drawParallelChart = (data: HeatwaveData[]) => {
      if (!parallelRef.value) return;
      const dimensions = [
        { label: '纬度 (°N)', values: data.map(r => Number(r.lat)) },
        { label: '经度 (°E)', values: data.map(r => Number(r.lon)) },
        { label: '持续时间 (天)', values: data.map(r => Number(r.duration)) },
        { label: '最大SST异常 (°C)', values: data.map(r => Number(r.max_anomaly)) },
        { label: '累积SST异常 (°C·d)', values: data.map(r => Number(r.cumulative_anomaly)) },
        { label: '最大基线调整异常 (°C)', values: data.map(r => Number(r.baa_max)) },
        { label: 'DHW峰值 (°C·week)', values: data.map(r => Number(r.DHW_peak)) }
      ];
      const layout = {
        title: { text: '海洋热浪事件多维特征平行坐标图', font: { size: 16, color: '#fff' } },
        paper_bgcolor: '#222', plot_bgcolor: '#222', font: { color: '#fff' }
      };
      Plotly.newPlot(parallelRef.value, [{
        type: 'parcoords',
        line: { color: data.map(r => Number(r.max_anomaly)), colorscale: 'Viridis', colorbar: { title: '最大SST异常 (°C)', titleside: 'right' } },
        dimensions
      }], layout);
    };

    // Plotly Time Series Chart
    const drawTimeSeriesChart = (data: HeatwaveData[]) => {
      if (!timeSeriesRef.value) return;
      const dateRange = Array.from({ length: 61 }, (_, i) => {
        const date = new Date('2020-03-01');
        date.setDate(date.getDate() + i);
        return date.toISOString().slice(0, 10);
      });
      const dailyStats = new Map<string, Map<string, { sum: number, count: number }>>();
      dateRange.forEach(date => { dailyStats.set(date, new Map()); });
      data.forEach(row => {
        if (!row.start_date || !row.duration || row.max_anomaly === undefined || row.max_anomaly === null) return;
        const startDate = new Date(row.start_date);
        const duration = Number(row.duration);
        const lat = Number(row.lat);
        const latBand = categorize.latBand(lat);
        const anomaly = Number(row.max_anomaly);
        for (let i = 0; i < duration; i++) {
          const currentDate = new Date(startDate);
          currentDate.setDate(startDate.getDate() + i);
          const dateStr = currentDate.toISOString().slice(0, 10);
          if (dailyStats.has(dateStr)) {
            const bandStats = dailyStats.get(dateStr)!;
            if (!bandStats.has(latBand)) { bandStats.set(latBand, { sum: 0, count: 0 }); }
            const stats = bandStats.get(latBand)!;
            stats.sum += anomaly;
            stats.count++;
          }
        }
      });
      const latBands = ['低纬（<40°N）', '中纬（40-45°N）', '高纬（≥45°N）'];
      const colors = ['#ff7f0e', '#2ca02c', '#1f77b4'];
      const traces = latBands.map((band, index) => ({
        type: 'scatter', mode: 'lines+markers', name: band, x: dateRange,
        y: dateRange.map(date => {
          const stats = dailyStats.get(date)?.get(band);
          return stats && stats.count > 0 ? Math.round((stats.sum / stats.count) * 100) / 100 : null;
        }),
        connectgaps: true, line: { color: colors[index], width: 2 }, marker: { size: 6, symbol: 'circle' }
      }));
      const layout = {
        title: { text: '不同纬度带日平均SST异常强度', font: { size: 16, color: '#fff' } },
        xaxis: { title: { text: '日期', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444', tickformat: '%Y-%m-%d' },
        yaxis: { title: { text: '平均SST异常 (°C)', font: { color: '#fff' } }, tickfont: { color: '#fff' }, gridcolor: '#444' },
        paper_bgcolor: '#222', plot_bgcolor: '#222', legend: { font: { color: '#fff' }, bgcolor: '#222' },
        hovermode: 'x unified', hoverlabel: { namelength: -1 }
      };
      Plotly.newPlot(timeSeriesRef.value, traces, layout);
    };

    // Plotly Sankey Chart
    const drawSankeyChart = (data: HeatwaveData[]) => {
      if (!sankeyRef.value) return;
      const { latBand, durationLevel, anomalyLevel } = categorize;
      const nodes: string[] = [];
      const links: any[] = [];
      const linkValues = new Map<string, number>();
      data.forEach(row => {
        const lat = latBand(Number(row.lat));
        const duration = durationLevel(Number(row.duration));
        const anomaly = anomalyLevel(Number(row.max_anomaly));
        [lat, duration, anomaly].forEach(node => { if (!nodes.includes(node)) nodes.push(node); });
        const key1 = `${lat}|${duration}`;
        const key2 = `${duration}|${anomaly}`;
        linkValues.set(key1, (linkValues.get(key1) || 0) + 1);
        linkValues.set(key2, (linkValues.get(key2) || 0) + 1);
      });
      linkValues.forEach((value, key) => {
        const [source, target] = key.split('|');
        links.push({ source: nodes.indexOf(source), target: nodes.indexOf(target), value: value });
      });
      Plotly.newPlot(sankeyRef.value, [{
        type: 'sankey',
        node: { pad: 15, thickness: 20, line: { color: 'black', width: 0.5 }, label: nodes, color: nodes.map(() => '#3366cc') },
        link: { source: links.map(l => l.source), target: links.map(l => l.target), value: links.map(l => l.value) }
      }], {
        title: '海洋热浪事件流向图', paper_bgcolor: '#222', plot_bgcolor: '#222', font: { color: '#fff', size: 12 }
      });
    };

    // Plotly Parallel Sankey Chart (using Parcoords)
    const drawParallelSankeyChart = (data: HeatwaveData[]) => {
      if (!parallelSankeyRef.value) return;
      const { latBand } = categorize;
      const groups = new Map<string, HeatwaveData[]>();
      data.forEach(row => {
        const band = latBand(Number(row.lat));
        if (!groups.has(band)) groups.set(band, []);
        groups.get(band)!.push(row);
      });
      const traces: any[] = [];
      const colors = ['#1f77b4', '#ff7f0e', '#2ca02c'];
      Array.from(groups.entries()).forEach(([band, rows], index) => {
        traces.push({
          type: 'parcoords', line: { color: colors[index] },
          dimensions: [
            { label: '最大SST异常（°C）', values: rows.map(r => Number(r.max_anomaly)) },
            { label: '累积SST异常（°C·d）', values: rows.map(r => Number(r.cumulative_anomaly)) },
            { label: 'DHW峰值（°C·week）', values: rows.map(r => Number(r.DHW_peak)) }
          ],
          name: band
        });
      });
      Plotly.newPlot(parallelSankeyRef.value, traces, {
        title: '不同纬度带特征对比', paper_bgcolor: '#222', plot_bgcolor: '#222', font: { color: '#fff' }
      });
    };

    // Plotly 2D Scatter Matrix Plot
    const drawScatterMatrix = (data: HeatwaveData[]) => {
      if (!scatterMatrixRef.value) return;
      const validData = data.filter(d =>
        d.lat !== undefined && d.lat !== null && d.lon !== undefined && d.lon !== null &&
        d.duration !== undefined && d.duration !== null && d.max_anomaly !== undefined && d.max_anomaly !== null &&
        !isNaN(Number(d.lat)) && !isNaN(Number(d.duration)) && !isNaN(Number(d.max_anomaly))
      );
      const traces = [{
        type: 'splom',
        dimensions: [
          { label: '纬度 (°N)', values: validData.map(d => Number(d.lat)) },
          { label: '持续时间 (天)', values: validData.map(d => Number(d.duration)) },
          { label: '最大SST异常 (°C)', values: validData.map(d => Number(d.max_anomaly)) }
        ],
        text: validData.map(d =>
          `纬度: ${d.lat}°N<br>` + `持续时间: ${d.duration}天<br>` + `最大SST异常: ${d.max_anomaly}°C`
        ),
        marker: {
          size: 6, color: validData.map(d => Number(d.cumulative_anomaly)), colorscale: 'Viridis',
          colorbar: { title: { text: '累积SST异常 (°C·d)', side: 'right', font: { color: '#fff' } }, tickfont: { color: '#fff' } },
          showscale: true, opacity: 0.6
        },
        hovertemplate: '%{text}<extra></extra>', diagonal: {visible: false}
      }];
      const layout = {
        title: { text: '海洋热浪特征散点矩阵', font: { size: 16, color: '#fff' } },
        width: 800, height: 800, paper_bgcolor: '#222', plot_bgcolor: '#222', font: { color: '#fff' },
        grid: {rows: 3, columns: 3, pattern: 'independent'}, showlegend: false, dragmode: 'select'
      };
      const config = { responsive: true, displayModeBar: true, displaylogo: false };
      Plotly.purge(scatterMatrixRef.value);
      Plotly.newPlot(scatterMatrixRef.value, traces, layout, config);
    };

    // Plotly Sunburst Chart
    const drawSunburstChart = (data: HeatwaveData[]) => {
      if (!sunburstRef.value) return;
      const { getYear, latBand, durationLevel } = categorize;
      const hierarchy: any = {};
      const nodeSums: Record<string, number> = {};
      data.forEach(row => {
        const year = getYear(row.start_date);
        const lat = Number(row.lat);
        const duration = Number(row.duration);
        if (isNaN(lat) || isNaN(duration)) return;
        if (!hierarchy[year]) hierarchy[year] = {};
        if (!hierarchy[year][latBand(lat)]) hierarchy[year][latBand(lat)] = {};
        if (!hierarchy[year][latBand(lat)][durationLevel(duration)]) hierarchy[year][latBand(lat)][durationLevel(duration)] = 0;
        hierarchy[year][latBand(lat)][durationLevel(duration)]++;
        const yearKey = year;
        const latKey = `${year}-${latBand(lat)}`;
        nodeSums[yearKey] = (nodeSums[yearKey] || 0) + 1;
        nodeSums[latKey] = (nodeSums[latKey] || 0) + 1;
      });
      const ids: string[] = [];
      const labels: string[] = [];
      const parents: string[] = [];
      const values: number[] = [];
      Object.entries(hierarchy).forEach(([year, yearData]: [string, any]) => {
        ids.push(year); labels.push(year); parents.push(''); values.push(nodeSums[year]);
        Object.entries(yearData).forEach(([lat, latData]: [string, any]) => {
          const latId = `${year}-${lat}`;
          ids.push(latId); labels.push(lat); parents.push(year); values.push(nodeSums[latId]);
          Object.entries(latData).forEach(([duration, count]: [string, number]) => {
            const durationId = `${latId}-${duration}`;
            ids.push(durationId); labels.push(duration); parents.push(latId); values.push(count);
          });
        });
      });
      Plotly.newPlot(sunburstRef.value, [{
        type: 'sunburst', ids, labels, parents, values, branchvalues: 'total'
      }], {
        title: '海洋热浪事件多层分布 (Plotly Sunburst)', paper_bgcolor: '#222', plot_bgcolor: '#222', font: { color: '#fff' }
      });
    };

    // Plotly Line Chart
    const drawLineChart = (data: HeatwaveData[]) => {
      if (!lineRef.value) return;
      const { latBand } = categorize;
      const timeSeriesData = new Map<string, Map<string, number[]>>();
      const validData = data.filter(row =>
        row && row.start_date && row.lat !== undefined && row.max_anomaly !== undefined && row.max_anomaly !== null
      );
      validData.forEach(row => {
        try {
          const band = latBand(Number(row.lat));
          const dateStr = String(row.start_date);
          if (dateStr.length >= 7) {
            const date = dateStr.slice(0, 7);
            if (!timeSeriesData.has(band)) { timeSeriesData.set(band, new Map()); }
            const bandData = timeSeriesData.get(band)!;
            if (!bandData.has(date)) { bandData.set(date, []); }
            const anomaly = Number(row.max_anomaly);
            if (!isNaN(anomaly)) { bandData.get(date)!.push(anomaly); }
          }
        } catch (error) {
          console.warn('数据处理警告:', error);
        }
      });
      const traces = Array.from(timeSeriesData.entries())
        .filter(([_, data]) => data.size > 0)
        .map(([band, data]) => {
          const sortedDates = Array.from(data.keys()).sort();
          return {
            type: 'scatter', mode: 'lines+markers', name: band, x: sortedDates,
            y: sortedDates.map(date => {
              const values = data.get(date)!;
              return values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : null;
            }),
            line: { shape: 'spline' }
          };
        });
      if (traces.length > 0) {
        Plotly.newPlot(lineRef.value, traces, {
          title: '不同纬度带月均SST异常变化', paper_bgcolor: '#222', plot_bgcolor: '#222', font: { color: '#fff' },
          xaxis: { title: '时间', color: '#fff' }, yaxis: { title: '月均最大SST异常（°C）', color: '#fff' }
        });
      }
    };

    // --- 数据加载和所有图表初始化 ---
    const initCharts = async () => {
      try {
        const response = await fetch('/data/heatwave_events.csv');
        const csvText = await response.text();
        const result = Papa.parse<HeatwaveData>(csvText, { header: true });

        console.log('CSV 数据:', result.data);

        if (result.data && result.data.length > 0) {
          const validData = result.data.filter(
            (row) =>
              row.lat !== undefined && row.lat !== null &&
              row.lon !== undefined && row.lon !== null &&
              row.duration !== undefined && row.duration !== null &&
              row.max_anomaly !== undefined && row.max_anomaly !== null &&
              !isNaN(Number(row.lat)) &&
              !isNaN(Number(row.lon)) &&
              !isNaN(Number(row.duration)) &&
              !isNaN(Number(row.max_anomaly)),
          );
          console.log('有效数据:', validData);

          heatwaveRawData = validData; // 存储有效数据供后续切换使用

          // 清除所有 Plotly 图表实例
          // 确保 scatter3dRef 在这里被清除，以便重新绘制
          if (scatter3dRef.value) Plotly.purge(scatter3dRef.value);
          [parallelRef, sankeyRef, scatterMatrixRef, timeSeriesRef, sunburstRef, lineRef, parallelSankeyRef].forEach((ref) => {
            if (ref.value) Plotly.purge(ref.value);
          });

          // 清除所有 ECharts 图表实例
          if (transitionChart) {
            transitionChart.dispose();
            transitionChart = null;
          }
          if (treemapSunburstChart) {
            treemapSunburstChart.dispose();
            treemapSunburstChart = null;
          }

          // 绘制所有图表
          draw3DScatterPlot(heatwaveRawData); // 默认初始绘制 3D 散点图
          drawParallelChart(validData);
          drawSankeyChart(validData);
          drawParallelSankeyChart(validData);
          drawSunburstChart(validData);
          drawLineChart(validData);
          drawTimeSeriesChart(validData);
          drawScatterMatrix(validData);
          drawTransitionChart(validData);
          drawTreemapSunburstChart(validData);

        } else {
          throw new Error('无有效数据或数据格式不正确');
        }
      } catch (error: any) {
        console.error('数据加载失败:', error);
        // 在页面上显示错误信息
        const errorDiv = document.createElement('div');
        errorDiv.style.color = '#ff4444';
        errorDiv.textContent = `数据加载失败：${error.message || error}`;
        document.querySelector('.heatwave-container')?.appendChild(errorDiv);
      } finally {
        loading.value = false;
      }
    };

    // --- 窗口大小调整处理 ---
    const handleResize = () => {
      // 调整所有 Plotly 图表大小
      const plotlyRefs = [parallelRef, sankeyRef, parallelSankeyRef, sunburstRef, lineRef, scatter3dRef, timeSeriesRef, scatterMatrixRef];
      plotlyRefs.forEach(ref => {
        if (ref.value) Plotly.Plots.resize(ref.value);
      });
      // 调整所有 ECharts 图表大小
      if (transitionChart) {
        transitionChart.resize();
      }
      if (treemapSunburstChart) {
        treemapSunburstChart.resize();
      }
    };

    // --- 生命周期钩子 ---
    onMounted(() => {
      // 确保 DOM 元素已渲染，再初始化图表
      nextTick(() => {
        initCharts();
      });
      // 监听窗口大小变化事件
      window.addEventListener('resize', handleResize);
    });

    onUnmounted(() => {
      // 组件卸载时，清理所有图表实例，防止内存泄漏
      window.removeEventListener('resize', handleResize);
      const plotlyRefs = [parallelRef, sankeyRef, parallelSankeyRef, sunburstRef, lineRef, scatter3dRef, timeSeriesRef, scatterMatrixRef];
      plotlyRefs.forEach(ref => {
        if (ref.value) Plotly.purge(ref.value);
      });
      if (transitionChart) {
        transitionChart.dispose();
        transitionChart = null;
      }
      if (treemapSunburstChart) {
        treemapSunburstChart.dispose();
        treemapSunburstChart = null;
      }
    });

    // 暴露给模板的数据和方法
    return {
      loading,
      parallelRef,
      sankeyRef,
      parallelSankeyRef,
      sunburstRef,
      lineRef,
      scatter3dRef,
      timeSeriesRef,
      scatterMatrixRef,
      transitionRef,
      treemapSunburstRef,
      get3DViewButtonText, // 暴露按钮文本方法
      toggle3DScatterView // 暴露切换视图方法
    };
  }
});
</script>

<style scoped>
/* --- 基础布局和样式 --- */
.heatwave-container {
  padding: 20px;

  min-height: 50vh; /* 最小高度占满视口 */
  color: #fff; /* 默认文字颜色 */
}

h2 {
  color: #FFFFFF;
  text-align: center;
  margin-bottom: 20px;
}

.unit-desc {
  color: #eee;
  font-size: 14px;
  background: #232323; /* 略深于背景的卡片色 */
  border-radius: 6px;
  padding: 10px 16px;
  margin-bottom: 20px;
  line-height: 1.7;
}

.unit-desc a {
  color: #61dafb; /* 链接颜色 */
  text-decoration: none;
}

.unit-desc a:hover {
  text-decoration: underline;
}

/* --- 图表容器通用样式 --- */
.chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
  gap: 20px;
  padding: 10px;
}

.chart-container {
  background-color: #232323;
  border-radius: 8px;
  padding: 15px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
  min-height: 300px; /* 最小高度避免塌陷 */
  height: auto; /* 自适应内容 */
  position: relative;
  display: flex;
  flex-direction: column;
}

/* 针对 3D 散点图的特定高度 */
.chart-container-3d {
  height: 600px;
}

/* 针对散点矩阵图的特定布局 */
.matrix-container {
  height: 800px; /* 散点矩阵图可能需要更大空间 */
  margin: 20px auto; /* 居中显示 */
  max-width: 800px; /* 最大宽度限制 */
}

/* 针对特定 Plotly 图表的高度 */
#parallelSankeyChart,
#sunburstChart {
  height: 500px;
}

#treemapSunburstChart {
  height: 600px;
}

/* --- ECharts 切换图表样式 --- */
.transition-clickable {
  cursor: pointer; /* 提示用户可以点击 */
  border: 1px solid rgba(255, 255, 255, 0.2); /* 边框 */
  transition: border-color 0.3s ease; /* 鼠标悬停时的过渡效果 */
}

.transition-clickable:hover {
  border-color: #1f77b4; /* 悬停时边框颜色变化 */
}

.click-prompt {
  position: absolute;
  top: 10px;
  right: 10px;
  background-color: rgba(0, 0, 0, 0.5); /* 半透明背景 */
  color: #fff;
  padding: 5px 10px;
  border-radius: 4px;
  font-size: 12px;
  pointer-events: none; /* 确保不阻挡鼠标事件到图表本身 */
  z-index: 10;
}

/* --- 切换视图按钮样式 --- */
.chart-action-button {
  display: block; /* 块级元素，独占一行 */
  margin: 10px auto 20px; /* 上边距10，左右自动居中，下边距20 */
  padding: 8px 15px;
  background-color: #1f77b4; /* 蓝色背景 */
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s ease; /* 鼠标悬停时的背景色过渡 */
}

.chart-action-button:hover {
  background-color: #165b8f; /* 悬停时颜色变深 */
}
</style>